module vec_math;   implicit none; save;
  integer, parameter :: DUFF_SIZE = 8;
  public

public dot; 
 contains

function dot(minI, maxI, v, v2)  
  implicit none; 
  integer, intent(in) :: minI, maxI;
  real, dimension(minI:maxI), intent(in) :: v, v2;

  real :: dot = 0., s = 0.;
  integer :: count = maxI - minI + 1;
  integer :: start_n, n;
  integer :: i = minI;
  integer :: key = MOD(count, DUFF_SIZ);

  select case (key) 
    case (0)
      s = s + v(i) * v2(i);        i = i + 1;
    case (7)
      s = s + v(i) * v2(i);        i = i + 1;;
    case (6)        
      s = s + v(i) * v2(i);        i = i + 1;
    case (5)        
      s = s + v(i) * v2(i);        i = i + 1;
    case (4)        
      s = s + v(i) * v2(i);        i = i + 1;
    case (3)        
      s = s + v(i) * v2(i);        i = i + 1;
    case (2)        
      s = s + v(i) * v2(i);        i = i + 1;
    case (1)        
      s = s + v(i) * v2(i);        i = i + 1;
  end select 
  
  start_n = (count + DUFF_SIZE - 1) / DUFF_SIZE - 1;
  do n = start_n, 1, -1 
    s = s + v(i) * v2(i);      i = i + 1;  !1
    s = s + v(i) * v2(i);      i = i + 1;  !2
    s = s + v(i) * v2(i);      i = i + 1;  !3
    s = s + v(i) * v2(i);      i = i + 1;  !4
    s = s + v(i) * v2(i);      i = i + 1;  !5
    s = s + v(i) * v2(i);      i = i + 1;  !6
    s = s + v(i) * v2(i);      i = i + 1;  !7
    s = s + v(i) * v2(i);      i = i + 1;  !8
  end do
  dot = s 
end function dot

end module vec_math
 